def daily_event(context):
    for sec in g.sec_list:
        sec_his = get_history(count=60, frequency='1d', field=['close', 'low', 'high'],
                              security_list=sec, fq='pre', include=False)
        sec_his['up'] = sec_his['high'].shift(1).rolling(window=g.config['n1']).max()  # 上线
        sec_his['down'] = sec_his['low'].shift(1).rolling(window=g.config['n2']).min()  # 下线

        posInfo = get_position(sec)
        holdRet = posInfo.last_sale_price / posInfo.cost_basis - 1 if posInfo.cost_basis != 0 else 0

        count = 1 if posInfo.enable_amount > 0 else 0

        if holdRet <= g.config['sl']:
            order_target(sec, 0)
            log.info("{} 触发止损".format(sec))
        elif holdRet >= g.config['tp']:
            order_target(sec, 0)
            log.info("{} 触发止盈".format(sec))
        else:
            if count == 1:
                # 清仓:持有股票时监控昨日最低价是否低于下线，低于下线卖出
                if sec_his['low'][-1] < sec_his['down'][-1]:
                    vol = posInfo.enable_amount
                    if vol > 0:
                        order(sec, -vol)
                        count = 0
                        log.info("{} 出场".format(sec))

            if count == 0:
                # 入场
                if sec_his['high'][-1] > sec_his['up'][-1]:
                    price = posInfo.last_sale_price if posInfo.last_sale_price > 0 else sec_his['close'][-1]
                    vol = min(context.portfolio.cash / price, g.config['buy_amount'] / price) // 100 * 100
                    if vol > 0:
                        order(sec, vol)
                        count = 1
                        log.info("{} 入场".format(sec))


def sell(context):
    # 收盘前卖出不在股票池中的股票
    for sec in g.sell_list:
        posInfo = get_position(sec)
        if posInfo.enable_amount > 0:
            order_target(sec, 0)
            log.info("{} 不在今日股票池中，已卖出".format(sec))


def initialize(context):
    # 用户可修改参数
    g.config = {
        'buy_amount': 100000,  # 每次股票买入金额
        'event_time': '9:31',  # 触发时间
        'n1': 5,  # 唐其安通道买入参数-上轨
        'n2': 10,  # 唐其安通道卖出参数-下轨
        'sl': -0.05,  # 止损线
        'tp': 0.2,  # 止盈线
        'debug': True  # 调试模式开关
    }

    g.indictor_config = {
        "MA": [10, 15, 20, 1],  # 多头三均线参数
    }

    run_daily(context, daily_event, time=g.config['event_time'])
    run_daily(context, sell, time='14:50')


def before_trading_start(context, data):
    # 获取昨日持仓股票
    yst_hold = [v.sid for s, v in get_positions().items()]

    # 获取中小100股票池股票
    today_list = get_index_stocks('000852.SS')

    # 准备过滤后的股票池
    exist_stocks = []

    if g.config['debug']:
        log.info("========== 开始筛选股票 ==========")
        log.info("初始股票池数量: {}".format(len(today_list)))

    for sec in today_list:
        debug_info = {"股票": sec, "名称": get_stock_name(sec)[sec]}

        try:
            # 获取股票市值信息
            valuation = get_fundamentals(sec, table='valuation', fields=['total_value', 'float_value'])
            if valuation.empty:
                debug_info["原因"] = "无法获取市值数据"
                if g.config['debug']: log.debug(debug_info)
                continue

            total_value = valuation['total_value'][0]
            debug_info["总市值(亿)"] = round(total_value / 1e8, 2)

            # 条件1: 市值50-500亿
            if not (5e9 <= total_value <= 50e9):
                debug_info["原因"] = "市值不在50-500亿范围"
                if g.config['debug']: log.debug(debug_info)
                continue

            # 获取历史数据
            secData = get_history(30, '1d', ['close', 'open', 'high', 'low', 'volume', 'money'], sec, fq='pre',
                                  include=False)

            # 条件2: 最近30天无涨幅大于5%，无跌幅大于5%
            max_price = secData['close'].max()
            min_price = secData['close'].min()
            max_change = (max_price - min_price) / min_price
            debug_info["30日最大涨跌幅(%)"] = round(max_change * 100, 2)

            if max_change > 0.05:
                debug_info["原因"] = "30日内涨跌幅超过5%"
                if g.config['debug']: log.debug(debug_info)
                continue

            # 条件3: 最近3天，成交量大于2亿小于20亿
            recent_money = secData['money'][-3:].mean()
            debug_info["3日平均成交额(亿)"] = round(recent_money / 1e8, 2)

            if not (2e8 <= recent_money <= 20e8):
                debug_info["原因"] = "3日成交额不在2-20亿范围"
                if g.config['debug']: log.debug(debug_info)
                continue

            # 条件4: 昨日股价创最近30天新高
            yesterday_high = secData['high'][-1]
            max_30day_high = secData['high'].max()
            debug_info["昨日最高价"] = yesterday_high
            debug_info["30日最高价"] = max_30day_high

            if yesterday_high != max_30day_high:
                debug_info["原因"] = "昨日未创30日新高"
                if g.config['debug']: log.debug(debug_info)
                continue

            # 指标:MA
            if g.indictor_config['MA'][-1]:
                m1 = secData.close.rolling(g.indictor_config['MA'][0]).mean()
                m2 = secData.close.rolling(g.indictor_config['MA'][1]).mean()
                m3 = secData.close.rolling(g.indictor_config['MA'][2]).mean()
                condHold1 = m1[-1] > m2[-1] and m2[-1] > m3[-1] and m1[-2] > m2[-2] and m2[-2] > m3[-2] and m1[-1] > m1[
                    -2]
                debug_info["均线多头排列"] = condHold1
            else:
                condHold1 = False
                debug_info["均线多头排列"] = "未启用"

            if condHold1:
                exist_stocks.append(sec)
                debug_info["结果"] = "符合条件"
                if g.config['debug']: log.info(debug_info)
            else:
                debug_info["原因"] = "均线不符合多头排列"
                if g.config['debug']: log.debug(debug_info)

        except Exception as e:
            debug_info["原因"] = f"数据获取异常: {str(e)}"
            if g.config['debug']: log.debug(debug_info)
            continue

    # 今日股票池
    g.sec_list = list(set(exist_stocks))
    # 昨日在股票池，今日不在股票池的股票需要卖出
    g.sell_list = list(set(yst_hold) - set(g.sec_list))

    if g.config['debug']:
        log.info("========== 筛选结果 ==========")
        log.info("符合条件的股票数量: {}".format(len(g.sec_list)))
        log.info("符合条件的股票列表: {}".format(g.sec_list))
        log.info("需要卖出的股票列表: {}".format(g.sell_list))
        log.info("========== 筛选结束 ==========")


def handle_data(context, data):
    pass